﻿using System;
using System.Web;

namespace BoxBinary.AspectCache.Core.Helpers
{
    public class Path
    {
        public static string GenerateSafeFilenameForSerialization(string fileNameSeed)
        {
            #region Validate Parameters

            if (String.IsNullOrEmpty(fileNameSeed))
                throw new ArgumentNullException("fileNameSeed");

            #endregion

            // Generate a filename for the serialized version of the cache item,
            // prefixing it with the machine name so that we can identify the source
            // of the serialized file without having to incur a deserialization hit
            return
                String.Concat(GetSuffixForAppDomainSpecificFilename(), IO.GetSafeFileName(fileNameSeed),
                              IO.SerializationFileNameExtension);
        }

        public static string RemoveExtension(string path)
        {
            int extensionIndex = path.LastIndexOf('.');
            return extensionIndex >= 0 ? path.Substring(0, extensionIndex) : path;
        }

        /// <summary>
        /// Combine web url paths.
        /// </summary>
        /// <param name="basePath"></param>
        /// <param name="relativePath"></param>
        /// <returns></returns>
        public static string CombinePaths(string basePath, string relativePath)
        {
            //return VirtualPathUtility.Combine(basePath + (basePath.EndsWith("/") ? "" : "/"), relativePath);
            string returnString = basePath;
            if (!String.IsNullOrEmpty(relativePath))
            {
                relativePath = relativePath.TrimStart('/');
                returnString += ((returnString.EndsWith("/") ? "" : "/") + relativePath);
            }
            return returnString;
        }

        public static string CombinePaths(string basePath, params string[] relativePaths)
        {
            string returnPath = basePath;
            foreach (string relativePath in relativePaths)
            {
                /*
                 * When an invocation is ambiguous,
                 * the compiler chooses the non-params
                 * method.
                 */
                returnPath = CombinePaths(returnPath, relativePath);
            }
            return returnPath;
        }

        public static string GenerateSafePathForSerialization(string rootDirPath, string fileNameSeed)
        {
            #region Validate Parameters

            if (String.IsNullOrEmpty(rootDirPath))
                throw new ArgumentNullException("rootDirPath");

            if (String.IsNullOrEmpty(fileNameSeed))
                throw new ArgumentNullException("fileNameSeed");

            #endregion

            return System.IO.Path.Combine(rootDirPath, GenerateSafeFilenameForSerialization(fileNameSeed));
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public static string GetSuffixForAppDomainSpecificFilename()
        {
            return
                String.Concat(
                                 IO.GetSafeFileName(String.Format("{0}/{1}", Environment.MachineName,
                                                                  HttpRuntime.AppDomainAppId)),
                                 "_");
        }


        /// <summary>
        /// Gets the directory name of a path
        /// </summary>
        /// <param name="uriPath"></param>
        /// <returns></returns>
        public static string GetUriDirectoryName(string uriPath)
        {
            string trimmedPath = uriPath.Trim('/');
            int LastSlash = trimmedPath.LastIndexOf('/');
            if (LastSlash == 0)
            {
                // Root folder
                return trimmedPath;
            }
            else
                return trimmedPath.Substring(LastSlash + 1);
        }

        /// <summary>
        /// Provides a static method to map a virtual path to an absolute one by combining it with the value of <see cref="HttpRuntime.AppDomainAppPath"/>
        /// </summary>
        /// <param name="relativeFilePath"></param>
        /// <returns></returns>
        /// <remarks>Note that if the path is already rooted no modification is performed</remarks>
        public static string StaticMapPath(string relativeFilePath)
        {
            #region Validate Parameters

            if (relativeFilePath == null)
                // Set to an empty string rather than throwing an exception
                relativeFilePath = "";

            #endregion

            if (System.IO.Path.IsPathRooted(relativeFilePath))
                return relativeFilePath;
            else
            {
                string rootPath = HttpRuntime.AppDomainAppPath;
                relativeFilePath = relativeFilePath.Replace("/", "\\").TrimStart('~').TrimStart('\\');
                return System.IO.Path.Combine(rootPath, relativeFilePath);
            }
        }

        /// <summary>
        /// Establishes whether a path could have been generated from calling <see cref="GenerateSafePathForSerialization"/>
        /// on this machine and within this same <see cref="HttpRuntime.AppDomainAppId"/>, by checking to see if it starts with <see cref="GetSuffixForAppDomainSpecificFilename"/>.
        /// </summary>
        /// <param name="path"></param>
        /// <returns></returns>
        public static bool IsSerializedPathFromThisAppDomain(string path)
        {
            #region Validate Parameters

            if (String.IsNullOrEmpty(path))
                throw new ArgumentNullException("path");

            #endregion

            path = System.IO.Path.GetFileName(path) + "";
            if (path.StartsWith(GetSuffixForAppDomainSpecificFilename(), StringComparison.InvariantCultureIgnoreCase))
                return true;
            else
                return false;
        }
    }
}